//////////////////////////////////////////////////////////////////////////
///	\file:	MThread.cpp
///	Copyright (MingYou) 2009 - All Rights Reserved
///	Author:	Robert.Ma
///	Date:	[2009/04/28]
///	Description:
///
//////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "MThread.h"
#include "InlineFunction.h"

CMMutex::CMMutex(HANDLE hObject)
		: m_hObject(hObject)
{}

CMMutex::~CMMutex()
{
	try
	{
		UnLock();
		::ErasePoiter(m_hObject);
	}
	catch (...)
	{}
}

bool CMMutex::Lock(DWORD dwWait)
{
	if ( (WAIT_OBJECT_0 == ::WaitForSingleObject(m_hObject, dwWait)) )
	{
		return true;
	}
	else
	{
		ASSERT(FALSE);

		return false;
	}
}

void CMMutex::UnLock()
{
	::ReleaseMutex(m_hObject);
}

CMThread::CMThread(void)
: m_hThread(NULL),
m_dwThreadID(ULONG_MAX),
m_dwErrorID(0)
{}

CMThread::~CMThread(void)
{
	try
	{
		Close();
	}
	catch (...)
	{}
}

HANDLE CMThread::Create(DWORD* lpID)
{
	if ( NULL == m_hThread )
	{
		PreCreate();
		m_hThread = ::CreateThread(NULL, 0, Run, this, 0, &m_dwThreadID);
	}

	if ( NULL != m_hThread )
	{
		if ( NULL != lpID )
		{
			*lpID = m_dwThreadID;
		}

		AfterCreate();

		return m_hThread;
	}
	else
	{
		m_dwErrorID = ::GetLastError();
		m_dwThreadID = ULONG_MAX;

		return NULL;
	}
}

DWORD CMThread::Run(LPVOID pParam)
{
	CMThread* pThread = (CMThread*)pParam;

	return pThread->Execute();
}

void CMThread::Close()
{
	PreClose();

	int iWatchDog = 0;
	while ( dwMaxThreadTerminationWaitCount > (iWatchDog++) )
	{
		::SetThreadPriority(m_hThread, THREAD_PRIORITY_HIGHEST);
		if ( (::WaitForSingleObject(m_hThread, dwThreadWaitTime) != WAIT_TIMEOUT) )
		{
			if ( NULL != m_hThread )
			{
				if ( ::CloseHandle(m_hThread) )
				{
					m_hThread = NULL;
				}
				else
				{
					ASSERT(FALSE);
				}
			}
			break;
		}
	}

	m_dwThreadID = ULONG_MAX;
	m_dwErrorID = 0;

	AfterClose();
}

HANDLE CMThread::GetThreadHandle() const
{
	return m_hThread;
}

DWORD CMThread::GetThreadID() const
{
	return m_dwThreadID;
}

DWORD CMThread::GetThreadErrorID() const
{
	return m_dwErrorID;
}

BOOL CMThread::SafePostMessage(DWORD idThread, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	return ::PostThreadMessage(idThread, Msg, wParam, lParam);
}
